package com.zxp.web.config.springSecurity.filter;

import com.alibaba.druid.util.StringUtils;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.zxp.web.config.springSecurity.detailService.CustomerUserDetailService;
import com.zxp.web.config.springSecurity.exeptions.CustomAuthenionException;
import com.zxp.web.config.springSecurity.handler.LoginFailHandler;
import com.zxp.web.jwt.JwtUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author MasterZ
 * @Date 2025/10/7 20:23
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Component
public class CheckTokenFilter extends OncePerRequestFilter {
    @Value("#{'${ignore.url}'.split(',')}")
    private List<String> ignoreUrls = Collections.emptyList();
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private CustomerUserDetailService customerUserDetailService;
    @Autowired
    LoginFailHandler loginFailHandler;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //验证码和登陆不需要验证
        try {
            //获取请求的URI
            String uri = request.getRequestURI();
            if (!ignoreUrls.contains(uri)) {
                validateToken(request);
            }
        } catch (AuthenticationException e) {
            loginFailHandler.commence(request, response, e);
            return;
        }
        filterChain.doFilter(request, response);
    }

    protected void validateToken(HttpServletRequest request) {
        //从请求头获取token
        String token = request.getHeader("token");
        //如果请求头的token为空，则从参数获取
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        if (StringUtils.isEmpty(token)) {
            throw new CustomAuthenionException("请传递token");
        }
        //验证token
        if (!jwtUtils.verify(token)) {
            throw new CustomAuthenionException("非法的token");
        }
        //解析token,获取登陆帐户
        DecodedJWT decodedJWT = jwtUtils.jwtDecode(token);
        Map<String, Claim> claims = decodedJWT.getClaims();
        String username = claims.get("username").asString();
        //用户认证
        UserDetails user = customerUserDetailService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
}
